"""提供与热门搜索词相关的功能的服务模块."""
from datetime import date, datetime, timedelta
from typing import List

from cachetools import TTLCache, cached
from cachetools.keys import hashkey
from fastapi import Request
from sqlalchemy import delete, desc, exists, func, select
from sqlalchemy.exc import SQLAlchemyError
from core.database import db_session
from core.models import Popular
from lib.common import get_client_ip
from service import BaseService


class PopularService(BaseService):
    """一类注入一类热门搜索词相关服务."""

    def __init__(self, db: db_session):
        self.db = db

    @classmethod
    async def async_init(cls, db: db_session):
        instance = cls(db)
        return instance

    def raise_exception(self, status_code: int, detail: str = None):
        pass

    @cached(TTLCache(maxsize=128, ttl=60),
            key=lambda self, limit=10, day=3: hashkey("populars", limit, day))
    def fetch_populars(self, limit: int = 10, day: int = 3) -> List[Popular]:
        """
        当前日期和 day我们提前查找日期之间的热门搜索词.
        - TTL(Time To Live)使用缓存查找.

        Args:
            limit (int, optional): 查询的数量. Defaults to 7.
            day (int, optional): 从今天开始 {day}前一天. Defaults to 3.

        Returns:
            List[Popular]: 热门搜索词列表

        """
        today = datetime.now()
        before_day = today - timedelta(days=day)
        populars = self.db.execute(
            select(Popular.pp_word, func.count(Popular.pp_word).label('count'))
            .where(
                Popular.pp_word != '',
                Popular.pp_date >= before_day,
                Popular.pp_date <= today
            )
            .group_by(Popular.pp_word)
            .order_by(desc('count'), Popular.pp_word)
            .limit(limit)
        ).all()

        return populars

    def create_popular(self, request: Request, fields: str, word: str) -> None:
    #    “创建热门搜索词。”
        try:
            if not word or not fields:
                self.raise_exception(400, "没有搜索词.")
                return None

            if "mb_id" in fields:  # 不使用会员ID进行搜索
                self.raise_exception(400, "不使用会员ID进行搜索。")
                return None

            today_date = datetime.now()
            exists_popular = self.db.scalar(
                exists(Popular)
                .where(
                    Popular.pp_word == word,
                    Popular.pp_date == today_date.strftime("%Y-%m-%d")
                ).select()
            )

            if exists_popular:
                self.raise_exception(409, "搜索词已注册.")
                return None

            # 如果当前日期没有热门搜索词，您将注册一个新的搜索词。.
            popular = Popular(
                pp_word=word,
                pp_date=today_date,
                pp_ip=get_client_ip(request))
            self.db.add(popular)
            self.db.commit()
        except SQLAlchemyError:
            pass
        return None

    def delete_populars(self, base_date: date) -> int:
        """删除基准日期之前的热门搜索词."""
        result = self.db.execute(
            delete(Popular).where(Popular.pp_date < base_date)
        )
        self.db.commit()
        return result.rowcount
